package small.common.designPattern.structure.proxy;

import small.common.core.util.ClassUtil;
import small.common.log.LogProvider;
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.PointcutPrimitive;
import org.slf4j.Logger;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * 正则匹配
 *
 * @Author zhoujin
 * @Date 2022/6/26 17:18
 */
public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodMatcher {

    private static final Logger logger = LogProvider.getLogger(AspectJExpressionPointcut.class);

    private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();

    static {
        SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
    }

    private PointcutExpression pointcutExpression = null;


    public AspectJExpressionPointcut(String expression) {
        PointcutParser pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution
                (SUPPORTED_PRIMITIVES, ClassUtil.getDefaultClassLoader());
        try {
            pointcutExpression = pointcutParser.parsePointcutExpression(expression);
        } catch (Exception e) {
            logger.warn(e.getMessage());
        }
    }

    @Override
    public boolean matches(Class<?> clazz) {
        if (pointcutExpression == null) {
            return false;
        }
        return pointcutExpression.couldMatchJoinPointsInType(clazz);
    }

    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        if (pointcutExpression == null) {
            return false;
        }
        return pointcutExpression.matchesMethodExecution(method).alwaysMatches();
    }

    @Override
    public ClassFilter getClassFilter() {
        return this;
    }

    @Override
    public MethodMatcher getMethodMatcher() {
        return this;
    }


}
